listitem: Move position/item/selected tracking to widget
authorBenjamin Otte <otte@redhat.com>
Sun, 3 Nov 2019 02:34:56 +0000 (03:34 +0100)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 30 May 2020 23:26:46 +0000 (19:26 -0400)
This way, we can ensure it's always there when we need it (before the
item gets created) and gone when we don't (if some GC language holds on
to the item after we've destroyed the widget).

gtk/gtklistitem.c
gtk/gtklistitemprivate.h
gtk/gtklistitemwidget.c

index 79d3e12e78ccc16344827723ba9e0f69c75ea70f..01db2cdac4cd69a986c58dca202a7982c9a51960 100644 (file)
@@ -98,11 +98,15 @@ gtk_list_item_get_property (GObject    *object,
       break;
 
     case PROP_ITEM:
-      g_value_set_object (value, self->item);
+      if (self->owner)
+        g_value_set_object (value, gtk_list_item_widget_get_item (self->owner));
       break;
 
     case PROP_POSITION:
-      g_value_set_uint (value, self->position);
+      if (self->owner)
+        g_value_set_uint (value, gtk_list_item_widget_get_position (self->owner));
+      else
+        g_value_set_uint (value, GTK_INVALID_LIST_POSITION);
       break;
 
     case PROP_SELECTABLE:
@@ -110,7 +114,10 @@ gtk_list_item_get_property (GObject    *object,
       break;
 
     case PROP_SELECTED:
-      g_value_set_boolean (value, self->selected);
+      if (self->owner)
+        g_value_set_boolean (value, gtk_list_item_widget_get_selected (self->owner));
+      else
+        g_value_set_boolean (value, FALSE);
       break;
 
     default:
@@ -259,7 +266,10 @@ gtk_list_item_get_item (GtkListItem *self)
 {
   g_return_val_if_fail (GTK_IS_LIST_ITEM (self), NULL);
 
-  return self->item;
+  if (self->owner == NULL)
+    return NULL;
+
+  return gtk_list_item_widget_get_item (self->owner);
 }
 
 /**
@@ -316,23 +326,6 @@ gtk_list_item_set_child (GtkListItem *self,
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
 }
 
-void
-gtk_list_item_set_item (GtkListItem *self,
-                        gpointer     item)
-{
-  g_return_if_fail (GTK_IS_LIST_ITEM (self));
-  g_return_if_fail (item == NULL || G_IS_OBJECT (item));
-
-  if (self->item == item)
-    return;
-
-  g_clear_object (&self->item);
-  if (item)
-    self->item = g_object_ref (item);
-
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
-}
-
 /**
  * gtk_list_item_get_position:
  * @self: a #GtkListItem
@@ -345,23 +338,12 @@ gtk_list_item_set_item (GtkListItem *self,
 guint
 gtk_list_item_get_position (GtkListItem *self)
 {
-  g_return_val_if_fail (GTK_IS_LIST_ITEM (self), 0);
-
-  return self->position;
-}
-
-void
-gtk_list_item_set_position (GtkListItem *self,
-                            guint        position)
-{
-  g_return_if_fail (GTK_IS_LIST_ITEM (self));
-
-  if (self->position == position)
-    return;
+  g_return_val_if_fail (GTK_IS_LIST_ITEM (self), GTK_INVALID_LIST_POSITION);
 
-  self->position = position;
+  if (self->owner == NULL)
+    return GTK_INVALID_LIST_POSITION;
 
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_POSITION]);
+  return gtk_list_item_widget_get_position (self->owner);
 }
 
 /**
@@ -379,21 +361,10 @@ gtk_list_item_get_selected (GtkListItem *self)
 {
   g_return_val_if_fail (GTK_IS_LIST_ITEM (self), FALSE);
 
-  return self->selected;
-}
-
-void
-gtk_list_item_set_selected (GtkListItem *self,
-                            gboolean     selected)
-{
-  g_return_if_fail (GTK_IS_LIST_ITEM (self));
-
-  if (self->selected == selected)
-    return;
-
-  self->selected = selected;
+  if (self->owner == NULL)
+    return FALSE;
 
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+  return gtk_list_item_widget_get_selected (self->owner);
 }
 
 /**
index b84057f83829fed211062750400b5475d0cf0076..d8f8833313c782356255ce607f7bffc658966856 100644 (file)
@@ -32,23 +32,14 @@ struct _GtkListItem
 
   GtkListItemWidget *owner; /* has a reference */
 
-  GObject *item;
   GtkWidget *child;
-  guint position;
 
   guint activatable : 1;
   guint selectable : 1;
-  guint selected : 1;
 };
 
 GtkListItem *   gtk_list_item_new                               (void);
 
-void            gtk_list_item_set_item                          (GtkListItem            *self,
-                                                                 gpointer                item);
-void            gtk_list_item_set_position                      (GtkListItem            *self,
-                                                                 guint                   position);
-void            gtk_list_item_set_selected                      (GtkListItem            *self,
-                                                                 gboolean                selected);
 
 G_END_DECLS
 
index 01cd0d28cd42817a097ca599be713a751759e1a0..1bda22fd1d5a7320c7ba12c9fbe7c108ba6ec96f 100644 (file)
@@ -29,6 +29,7 @@
 #include "gtklistitemfactoryprivate.h"
 #include "gtklistitemprivate.h"
 #include "gtkmain.h"
+#include "gtkselectionmodel.h"
 #include "gtkwidget.h"
 #include "gtkwidgetprivate.h"
 
@@ -37,6 +38,10 @@ struct _GtkListItemWidgetPrivate
 {
   GtkListItemFactory *factory;
   GtkListItem *list_item;
+
+  GObject *item;
+  guint position;
+  gboolean selected;
 };
 
 enum
@@ -54,13 +59,13 @@ gtk_list_item_widget_activate_signal (GtkListItemWidget *self)
 {
   GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
 
-  if (!priv->list_item->activatable)
+  if (priv->list_item && !priv->list_item->activatable)
     return;
 
   gtk_widget_activate_action (GTK_WIDGET (self),
                               "list.activate-item",
                               "u",
-                              priv->list_item->position);
+                              priv->position);
 }
 
 static gboolean
@@ -121,6 +126,7 @@ gtk_list_item_widget_dispose (GObject *object)
       gtk_list_item_factory_teardown (priv->factory, self);
       g_assert (priv->list_item == NULL);
     }
+  g_clear_object (&priv->item);
   g_clear_object (&priv->factory);
 
   G_OBJECT_CLASS (gtk_list_item_widget_parent_class)->dispose (object);
@@ -135,7 +141,7 @@ gtk_list_item_widget_select_action (GtkWidget  *widget,
   GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
   gboolean modify, extend;
 
-  if (!priv->list_item->selectable)
+  if (priv->list_item && !priv->list_item->selectable)
     return;
 
   g_variant_get (parameter, "(bb)", &modify, &extend);
@@ -143,7 +149,7 @@ gtk_list_item_widget_select_action (GtkWidget  *widget,
   gtk_widget_activate_action (GTK_WIDGET (self),
                               "list.select-item",
                               "(ubb)",
-                              priv->list_item->position, modify, extend);
+                              priv->position, modify, extend);
 }
 
 static void
@@ -229,13 +235,13 @@ gtk_list_item_widget_click_gesture_pressed (GtkGestureClick   *gesture,
   GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
   GtkWidget *widget = GTK_WIDGET (self);
 
-  if (!priv->list_item->selectable && !priv->list_item->activatable)
+  if (priv->list_item && !priv->list_item->selectable && !priv->list_item->activatable)
     {
       gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
       return;
     }
 
-  if (priv->list_item->selectable)
+  if (!priv->list_item || priv->list_item->selectable)
     {
       GdkModifierType state;
       GdkEvent *event;
@@ -250,17 +256,17 @@ gtk_list_item_widget_click_gesture_pressed (GtkGestureClick   *gesture,
       gtk_widget_activate_action (GTK_WIDGET (self),
                                   "list.select-item",
                                   "(ubb)",
-                                  priv->list_item->position, modify, extend);
+                                  priv->position, modify, extend);
     }
 
-  if (priv->list_item->activatable)
+  if (!priv->list_item || priv->list_item->activatable)
     {
       if (n_press == 2)
         {
           gtk_widget_activate_action (GTK_WIDGET (self),
                                       "list.activate-item",
                                       "u",
-                                      priv->list_item->position);
+                                      priv->position);
         }
     }
 
@@ -280,7 +286,7 @@ gtk_list_item_widget_enter_cb (GtkEventControllerFocus *controller,
   gtk_widget_activate_action (widget,
                               "list.scroll-to-item",
                               "u",
-                              priv->list_item->position);
+                              priv->position);
 }
 
 static void
@@ -381,6 +387,13 @@ gtk_list_item_widget_default_setup (GtkListItemWidget *self,
 
   if (list_item->child)
     gtk_list_item_widget_add_child (self, list_item->child);
+
+  if (priv->item)
+    g_object_notify (G_OBJECT (list_item), "item");
+  if (priv->position != GTK_INVALID_LIST_POSITION)
+    g_object_notify (G_OBJECT (list_item), "position");
+  if (priv->selected)
+    g_object_notify (G_OBJECT (list_item), "selected");
 }
 
 void
@@ -396,6 +409,13 @@ gtk_list_item_widget_default_teardown (GtkListItemWidget *self,
 
   if (list_item->child)
     gtk_list_item_widget_remove_child (self, list_item->child);
+
+  if (priv->item)
+    g_object_notify (G_OBJECT (list_item), "item");
+  if (priv->position != GTK_INVALID_LIST_POSITION)
+    g_object_notify (G_OBJECT (list_item), "position");
+  if (priv->selected)
+    g_object_notify (G_OBJECT (list_item), "selected");
 }
 
 void
@@ -405,9 +425,24 @@ gtk_list_item_widget_default_update (GtkListItemWidget *self,
                                      gpointer           item,
                                      gboolean           selected)
 {
-  gtk_list_item_set_item (list_item, item);
-  gtk_list_item_set_position (list_item, position);
-  gtk_list_item_set_selected (list_item, selected);
+  GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
+
+  /* FIXME: It's kinda evil to notify external objects from here... */
+  
+  if (g_set_object (&priv->item, item))
+    g_object_notify (G_OBJECT (list_item), "item");
+
+  if (priv->position != position)
+    {
+      priv->position = position;
+      g_object_notify (G_OBJECT (list_item), "position");
+    }
+
+  if (priv->selected != selected)
+    {
+      priv->selected = selected;
+      g_object_notify (G_OBJECT (list_item), "selected");
+    }
 }
 
 void
@@ -437,7 +472,7 @@ gtk_list_item_widget_get_position (GtkListItemWidget *self)
 {
   GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
 
-  return priv->list_item->position;
+  return priv->position;
 }
 
 gpointer
@@ -445,7 +480,7 @@ gtk_list_item_widget_get_item (GtkListItemWidget *self)
 {
   GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
 
-  return priv->list_item->item;
+  return priv->item;
 }
 
 gboolean
@@ -453,6 +488,6 @@ gtk_list_item_widget_get_selected (GtkListItemWidget *self)
 {
   GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
 
-  return priv->list_item->selected;
+  return priv->selected;
 }